using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Events;

public class GameManager : MonoBehaviour
{
    public static GameManager Instance;

    public Player player1;
    public Player player2;
    public Bird bird;
    public CamTarget camTarget;
    public GameObject prefabSoil;
    public GameObject prefabChips;
    public UnityEvent<int> GameOverEvt;
    public UnityEvent GameReadyEvt;
    public UnityEvent<int> ChipsEvt;

    private float m_remainTime;
    private float m_nextSoilTime;
    private float m_nextChipsTime;
    private float m_playTime = 0.0f;
    private bool m_bIsGameover = false;
    private bool m_bIsGameReady = false;

    public int RemainTime
    {
        get
        {
            return Mathf.CeilToInt(m_remainTime);
        }
    }

    public bool isPause
    {
        get
        {
            return !m_bIsGameReady || m_bIsGameover || Time.realtimeSinceStartup < m_playTime;
        }
    }
    public float LeftWall
    {
        get
        {
            return Mathf.Max(-17.0f, camTarget.transform.position.x - 8.0f);
        }
    }
    public float RightWall
    {
        get
        {
            return Mathf.Min(camTarget.transform.position.x + 8.0f, 17.0f);
        }
    }

    private void Awake()
    {
        Instance = this;
        m_remainTime = 3.0f;

        camTarget.player1 = player1;
        camTarget.player2 = player2;

        AudioManager.Instance.PlaySE("SE_11_GameReady");
    }

    public void AssignPlayer(int index, Player newPlayer)
    {
        if (index == 1)
            player1 = newPlayer;
        if (index == 2)
            player2 = newPlayer;
    }

    public bool CheckGameOver()
    {
        if (player1.HP <= 0)
            return true;
        if (player2.HP <= 0)
            return true;
        //if (Mathf.Abs(player1.HP - player2.HP) >= 3)
        //    return true;
        return false;
    }

    public bool CheckChips(Chips chips)
    {
        float dis1 = Mathf.Abs(player1.Pos.x - chips.transform.position.x);
        float dis2 = Mathf.Abs(player2.Pos.x - chips.transform.position.x);
        float minDis = Mathf.Min(dis1, dis2);
        if (minDis > 4.0f)
            return false;

        bird.gameObject.SetActive(true);
        Player deadPlayer = dis1 <= dis2 ? player1 : player2;
        deadPlayer.SetHP(0);
        bird.FlyTo(deadPlayer);
        chips.Fly(deadPlayer);
        ChipsEvt.Invoke(dis1 <= dis2 ? 1 : 2);
        return true;
    }

    public void GameReady()
    {
        m_bIsGameReady = true;
        Time.timeScale = 1.0f;

        m_remainTime = 180.0f;
        m_nextSoilTime = m_remainTime;
        m_nextChipsTime = 90.0f + Random.Range(0.0f, 30.0f);

        GameReadyEvt.Invoke();
    }

    public void GameOver()
    {
        int WinnerIndex = 0;
        if (player1.HP > player2.HP)
            WinnerIndex = 1;
        else if(player1.HP < player2.HP)
             WinnerIndex = 2;

        m_bIsGameover = true;
        Time.timeScale = 0;

        GameOverEvt.Invoke(WinnerIndex);
    }    

    private void Update()
    {
        if (isPause)
            Time.timeScale = 0.0f;
        if (!isPause)
            Time.timeScale = 1.0f;

        if (!m_bIsGameReady)
        {
            m_remainTime -= Time.unscaledDeltaTime;

            if (0 >= m_remainTime)
                GameReady();

            return;
        }

        if (isPause)
            return;

        m_remainTime -= Time.deltaTime;
        if (0 >= m_remainTime) {
            GameOver();
            return;
        }

        if (m_remainTime <= m_nextSoilTime)
            Lapidation();

        if (m_remainTime <= m_nextChipsTime)
            DropChips();
    }

    public void AddHP(int playerIndex)
    {
        if (playerIndex == 1)
            player1.Reverse();
        if (playerIndex == 2)
            player2.Reverse();
    }

    public void PauseFrame(float pauseTime)
    {
        m_playTime = Time.realtimeSinceStartup + pauseTime;
    }

    public void Lapidation()
    {
        float minX = player1.Pos.x - 3.0f;
        float maxX = player1.Pos.x + 3.0f;
        minX = Mathf.Min(minX, player2.Pos.x - 3.0f);
        maxX = Mathf.Max(maxX, player2.Pos.x + 3.0f);
        minX = Mathf.Max(-17.0f, minX);
        maxX = Mathf.Min(maxX, 17.0f);
        Instantiate(prefabSoil, new Vector3(Random.Range(minX, maxX), 8.0f), Quaternion.identity);

        m_nextSoilTime = m_remainTime - Random.Range(10.0f, 20.0f);
    }

    public void DropChips()
    {
        float minX = Mathf.Min(player1.Pos.x, player2.Pos.x);
        float maxX = Mathf.Max(player1.Pos.x, player2.Pos.x);
        float newX = Mathf.Clamp(Random.Range(minX, maxX), -17.0f, 17.0f);
        Instantiate(prefabChips, new Vector3(newX, 8.0f), Quaternion.identity);

        m_nextChipsTime -= Random.Range(50.0f, 60.0f);
    }

    public void LapidationWithVelocity(Vector3 position, Vector3 velocity)
    {
        var newSoil = Instantiate(prefabSoil, position, Quaternion.identity).GetComponent<Soil>();
        newSoil.invincibleTime = 0.3f;
        var soilRigidbody = newSoil.GetComponent<Rigidbody2D>();
        soilRigidbody.velocity = velocity;
    }
}
